package com.outsource.framework.util.unicom.news.sso.httpclient;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;

public class Broswer implements IBroswer
{
	private HttpClient httpClient;
	private static Log log = LogFactory.getLog(Broswer.class);

	@Override
	public HttpResponseWrapper get(String url)
	{
		return this.get(url, null, null);
	}

	@Override
	public HttpResponseWrapper get(String url, List<Header> headers)
	{
		return this.get(url, null, headers);
	}

	@Override
	public HttpResponseWrapper get(String url, Map<String, String> params,
			List<Header> headers)
	{
		long t = System.currentTimeMillis();

		HttpGet httpget = new HttpGet(url);

		if (headers != null && headers.size() > 0)
		{
			for (Header header : headers)
			{
				httpget.addHeader(header);
			}
		}

		try
		{
			if (params != null)
			{
				HttpParams httpParams = new BasicHttpParams();
				for (Entry<String, String> param : params.entrySet())
				{
					httpParams.setParameter(param.getKey(), param.getValue());
				}
				httpget.setParams(httpParams);
			}
			// Create a response handler
			return httpClient.execute(httpget, httpResponseHandler);
		} catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally
		{
			// do nth
			log.info("Agent request url:" + url + "\tcost:"
					+ (System.currentTimeMillis() - t));
			httpget.abort();
		}
	}

	@Override
	public HttpResponseWrapper post(String url, Map<String, String> params)
	{
		return post(url, params, null);
	}

	@Override
	public HttpResponseWrapper post(String url, Map<String, String> params,
			List<Header> headers)
	{
		long t = System.currentTimeMillis();
		HttpPost httppost = new HttpPost(url);
		if (headers != null && headers.size() > 0)
		{
			for (Header header : headers)
			{
				httppost.addHeader(header);
			}
		}

		if (params != null)
		{
			List<NameValuePair> formparams = new ArrayList<NameValuePair>();
			for (Entry<String, String> e : params.entrySet())
			{
				formparams
						.add(new BasicNameValuePair(e.getKey(), e.getValue()));
			}
			UrlEncodedFormEntity entity = null;
			try
			{
				entity = new UrlEncodedFormEntity(formparams, "UTF-8");
			} catch (UnsupportedEncodingException e)
			{
				e.printStackTrace();
			}

			httppost.setEntity(entity);
		}
		try
		{
			return httpClient.execute(httppost, httpResponseHandler);
		} catch (ClientProtocolException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
			throw new RuntimeException(e);

		} finally
		{
			log.info("Agent request url:" + url + "\tcost:"
					+ (System.currentTimeMillis() - t));
			httppost.abort();
		}
		return null;
	}

	@Override
	public void open()
	{

		SchemeRegistry schemeRegistry = new SchemeRegistry();
		schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory
				.getSocketFactory()));
		PlainSocketFactory.getSocketFactory();

		schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory
				.getSocketFactory()));

		ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(
				schemeRegistry);
		// Increase max total connection to 200
		cm.setMaxTotal(1000);
		// Increase default max connection per route to 20
		cm.setDefaultMaxPerRoute(500);
		// Increase max connections for localhost:80 to 50
		// HttpHost localhost = new HttpHost("locahost", 80);
		// cm.setMaxForRoute(new HttpRoute(localhost), 50);

		httpClient = new DefaultHttpClient();
		httpClient.getParams().setIntParameter("http.socket.timeout", 30000);
		httpClient.getParams().setIntParameter("http.connection.timeout", 1000);
		httpClient
				.getParams()
				.setParameter(
						CoreProtocolPNames.USER_AGENT,
						"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9");
	}

	@Override
	public void close()
	{
		httpClient.getConnectionManager().shutdown();
	}

	private ResponseHandler<HttpResponseWrapper> httpResponseHandler = new ResponseHandler<HttpResponseWrapper>()
	{

		@Override
		public HttpResponseWrapper handleResponse(
				org.apache.http.HttpResponse response)
				throws ClientProtocolException, IOException
		{
			return new HttpResponseWrapper(response);
		}
	};

	@Override
	public HttpResponseWrapper visit(String url, String method)
	{
		return this.visit(url, null, null, method);
	}

	@Override
	public HttpResponseWrapper visit(String url, Map<String, String> params,
			String method)
	{
		return this.visit(url, params, null, method);
	}

	@Override
	public HttpResponseWrapper visit(String url, Map<String, String> params,
			List<Header> headers, String method)
	{
		if ("POST".equalsIgnoreCase(method))
		{
			return this.post(url, params, headers);
		} else
		{
			return this.get(url, params, headers);
		}
	}
}
